package de.androidschoice.androids.choice.xml;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.net.ParseException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import de.androidschoice.androids.choice.interfaces.GameScene;
import de.androidschoice.androids.choice.interfaces.GameSceneChoice;
import de.androidschoice.androids.choice.objects.AndroidsChoiceGame;
import de.androidschoice.androids.choice.objects.AndroidsChoiceGameScene;
import de.androidschoice.androids.choice.objects.AndroidsChoiceGameSceneChoice;

/**
 *
 */
public class Xml2GameParser 
{
	public static final String XML_ATTRNAME_GAMETITLE = "title";
	public static final String XML_ATTRNAME_SCENETITLE = "title";
	
	public static final String XML_ELEMENTNAME_GAMEIMAGE = "image";
	public static final String XML_ELEMENTNAME_GAMESCENE = "scene";
	public static final String XML_ELEMENTNAME_GAMESCENECHOICE = "refscene";
	
	private Xml2GameParser(){};
	private static final Xml2GameParser INSTANCE = new Xml2GameParser();
	
	/**
	 * Singleton-Object abrufen
	 * @return
	 * Instanz des Xml2GameParsers
	 */
	public static Xml2GameParser getInstance()
	{
		return INSTANCE;
	}

	/**
	 * Parsen des XML-Textes aus der XML-Datei, deren Pfad angebenen wurde
	 * @param xmlFile
	 * Pfad zu der zu verwendenden XML-Datei
	 * @return
	 * AndroidsChoiceGame, welches aus der XML-Datei geparst wurde
	 * @throws IOException 
	 * Wenn Lesefehler aufgetreten sind.
	 * @throws SAXException 
	 * Bei Fehler beim Parsen des XML-Dokuments
	 * @throws ParserConfigurationException 
	 * Falls die Konfiguration des Parsers fehlerhaft ist
	 */
	public AndroidsChoiceGame parseAndroidsChoiceGameFromXML(String xmlFile) throws IOException, ParserConfigurationException, SAXException
	{
		return this.parseAndroidsChoiceGameFromXML(new File(xmlFile));
	}
	
	/**
	 * Erstellt ein neues AndroidsChoiceGame aus einer XML-Struktur, welche als Datei übergeben wurde
	 * @param xmlFile
	 * Die zu verwendende XML-Datei
	 * @return
	 * Das geparsete AndroidsChoiceGame
	 * @throws SAXException 
	 * Bei Fehler beim Parsen des XML-Dokuments
	 * @throws ParserConfigurationException 
	 * Falls die Konfiguration des Parsers fehlerhaft ist
	 * @throws IOException 
	 * Wenn Lesefehler aufgetreten sind
	 */
	public AndroidsChoiceGame parseAndroidsChoiceGameFromXML(File xmlFile) throws ParserConfigurationException, SAXException, IOException 
	{
		return createGameFromDocument(createDocument(xmlFile));
	}
	
	/**
	 * Erstellt ein neues AndroidsChoiceGame aus einer XML-Struktur, welche als String übergeben wurde
	 * @param xmlText
	 * Das XML-Dokument als String
	 * @return
	 * Das geparsete AndroidsChoiceGame
	 * @throws ParseException
	 * Falls das Parsen der XML-Struktur fehl schlug
	 * @throws ParserConfigurationException 
	 * Falls die Konfiguration des Parsers fehlerhaft ist
	 * @throws IOException
	 * Bei Lesefehler
	 * @throws SAXException
	 * Bei Fehler beim Parsen des XML-Dokuments
	 */
	public AndroidsChoiceGame parseAndroidsChoiceGameFromXMLString(String xmlText) throws ParserConfigurationException, SAXException, IOException
	{
		return createGameFromDocument(createDocument(xmlText));
	}
	
	/**
	 * erstellt ein neues DOM-Object aus der XML-Struktur
	 * @param xmlFile
	 * XML-Struktur als File
	 * @return
	 * Das XML-Document als DOM-Object
	 * @throws ParserConfigurationException
	 * Falls die Konfiguration des Parsers fehlerhaft ist
	 * @throws SAXException
	 * Bei Fehler beim Parsen des XML-Dokuments
	 * @throws IOException
	 * Bei Lesefehler
	 */
	private Document createDocument(File xmlFile) throws ParserConfigurationException, SAXException, IOException
	{
		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document document = db.parse(xmlFile);
		
		return document;
	}
	
	/**
	 * erstellt ein neues DOM-Object aus der XML-Struktur
	 * @param xmlText
	 * XML-Struktur als String
	 * @return
	 * Das XML-Document als DOM-Object
	 * @throws ParserConfigurationException
	 * Falls die Konfiguration des Parsers fehlerhaft ist
	 * @throws SAXException
	 * Bei Fehler beim Parsen des XML-Dokuments
	 * @throws IOException
	 * Bei Lesefehler
	 */
	private Document createDocument(String xmlText) throws ParserConfigurationException, SAXException, IOException
	{
		DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
		Document document = db.parse(new ByteArrayInputStream(xmlText.getBytes()));
		
		return document;
	}
	
	
	/**
	 * erstellt aus dem geparseten Dokument das gefüllte AndroidsChoiceGame
	 * @param document
	 * Die Xml-Datei, welche sämtliche Konfigurationen, Ressourcen und Links zu Ressourcen des gestarteten Spieles enthält
	 * @return
	 * 
	 */
	private AndroidsChoiceGame createGameFromDocument(Document document)
	{
		String title = "Dark Planet";
		String gameImage = null;
		File file = null;
		Element docElement = document.getDocumentElement();
		
//		title = docElement.getAttribute(XML_ATTRNAME_GAMETITLE);
//		gameImage = docElement.getElementsByTagName(XML_ELEMENTNAME_GAMEIMAGE).item(0).getFirstChild().getNodeValue();
		
		AndroidsChoiceGame game = new AndroidsChoiceGame(title, file);
		
//		System.out.println(docElement.getNodeName() + " -> " + title);
//		System.out.println(gameImage);
		
		AndroidsChoiceGameScene gameScene = null;
		GameSceneChoice gameSceneChoice = null;
		
		gameScene = new AndroidsChoiceGameScene(1, "\'Run!\' shouts the Doctor. And so you run - really fast.\nA few moments ago, you'd never even met this \'Doctor\' - but now you\'re doing exactly what he says. It makes sense. The last person he told to run didn\'t go anywhere and... well, it was hard to see what exactly happened... he just seemed to get swallowed up by the approaching shadows.", file);
		
		gameSceneChoice = new AndroidsChoiceGameSceneChoice(29, "Hit the red button!", file);
		gameScene.addGameSceneChoice(gameSceneChoice);
		gameSceneChoice = new AndroidsChoiceGameSceneChoice(51, "Hit the yellow button!", file);
		gameScene.addGameSceneChoice(gameSceneChoice);
		gameSceneChoice = new AndroidsChoiceGameSceneChoice(73, "Hit the green button!", file);
		gameScene.addGameSceneChoice(gameSceneChoice);
		
		game.addGameScene(gameScene);
		
		gameScene = new AndroidsChoiceGameScene(29, "There\'s a loud whooshing noise. Your stomach lurches. The floor drops away from beneath your feet, then it suddenly rushes back up again, knocking you you off balance. Martha puts an arm around you and holds you steady. The noise fades down to a gentle hum and the clanking and clicking of cooling machinery." +
				"\'Where are we?\' asks Martha. \'I'm not sure\', says the Doctor, looking at you. \'Which button did you press?\' You point to the red one. There's a pause and you wait to see if he's going to tell you off... but he just claps his hands and then rubs them together. \'Right!\' he says, brightly. " +
				"\'Well, before we can get you back to where we came from, we need to find out exactly where we are now.\'\n\'Brilliant\' says Martha, her eyes sparkling as she holds open the TARDIS door. \'After you!\' she says, and waves you through.", file);
		
		gameSceneChoice = new AndroidsChoiceGameSceneChoice(1, "Hit the red button!", file);
		gameScene.addGameSceneChoice(gameSceneChoice);
		
		
		game.addGameScene(gameScene);
		
		return game;
	}
}
